package midas.mw.crt.jxta;


import net.jxta.discovery.DiscoveryEvent;
import net.jxta.discovery.DiscoveryListener;
import net.jxta.discovery.DiscoveryService;
import net.jxta.document.Advertisement;
import net.jxta.exception.PeerGroupException;
import net.jxta.id.IDFactory;
import net.jxta.peergroup.PeerGroup;
import net.jxta.peergroup.PeerGroupID;
import net.jxta.platform.NetworkConfigurator;
import net.jxta.platform.NetworkManager;
import net.jxta.protocol.DiscoveryResponseMsg;

import java.text.MessageFormat;
import java.util.Enumeration;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import javax.security.cert.CertificateException;
import javax.swing.JOptionPane;

public class Node implements DiscoveryListener {

    public static final String Local_Network_Manager_Name = "My Local Network Manager";

    NetworkManager TheNetworkManager;
    NetworkConfigurator TheConfig;
    PeerGroup TheNetPeerGroup;

    private static final String MIDAS_GROUP_ID 	= "urn:jxta:uuid-0AF9A67371F841F8B6248C6A9B9120B502";
    
    
    public Node(int nodeType, String nodeName) {
        // Creating the Network Manager
        try {
            System.out.println("Creating the Network Manager");
            if (nodeType == 1)
            	TheNetworkManager = new NetworkManager(
                    NetworkManager.ConfigMode.SUPER, Local_Network_Manager_Name);
            else if (nodeType == 0)
            	TheNetworkManager = new NetworkManager(
                        NetworkManager.ConfigMode.EDGE, Local_Network_Manager_Name);            
            else
            	throw new IOException();
            System.out.println("Network Manager created");
        } catch (IOException ex) {
            ex.printStackTrace();
            System.exit(-1);
        }

        // Persisting it to make sure the Peer ID is not re-created each
        // time the Network Manager is instantiated
        TheNetworkManager.setConfigPersistent(true);
        
        System.out.println("PeerID: " + TheNetworkManager.getPeerID().toString());

        // Retrieving the Network Configurator
        System.out.println("Retrieving the Network Configurator");
        try {
            TheConfig = TheNetworkManager.getConfigurator();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("Network Configurator retrieved");

        // Does a local peer configuration exist?
        if (TheConfig.exists()) {

            System.out.println("Local configuration found");
            // We load it
            File LocalConfig = new File(TheConfig.getHome(), "PlatformConfig");
            try {
                System.out.println("Loading found configuration");
                TheConfig.load(LocalConfig.toURI());
                System.out.println("Configuration loaded");
            } catch (IOException ex) {
                ex.printStackTrace();
                System.exit(-1);
            } catch (CertificateException ex) {
                // An issue with the existing peer certificate has been encountered
                ex.printStackTrace();
                System.exit(-1);
            }
        } else {
            System.out.println("No local configuration found");
            TheConfig.setName(nodeName);
            TheConfig.setPrincipal("midas");
            TheConfig.setPassword("midas");

            System.out.println("Principal: " + TheConfig.getPrincipal());
            System.out.println("Password : " + TheConfig.getPassword());
            
            try {
            	TheConfig.setInfrastructureID((PeerGroupID )IDFactory.fromURI(new URI(MIDAS_GROUP_ID)));
            	TheConfig.setInfrastructureName("MIDAS NETWORK");  
            	//TheConfig.setInfrastructureDescriptionStr("Nodes running in the midas network");
			}catch (URISyntaxException use) { 
				use.printStackTrace();
	        }
			
			URI seedingURI = new File("CentralNodes.txt").toURI();  
			TheConfig.addRdvSeedingURI(seedingURI);
			TheConfig.addRelaySeedingURI(seedingURI);
			TheConfig.setUseOnlyRelaySeeds(true);
			TheConfig.setUseOnlyRendezvousSeeds(true);

            try {
                System.out.println("Saving new configuration");
                TheConfig.save();
                System.out.println("New configuration saved successfully");
            } catch (IOException ex) {
                ex.printStackTrace();
                System.exit(-1);
            }
        }
        
        try {
        	//TheNetworkManager.startNetwork();
        	System.out.println("Starting JXTA");
            TheNetPeerGroup = TheNetworkManager.startNetwork();
            System.out.println("JXTA Started");
            
            System.out.println("Peer name      : "
                    + TheNetPeerGroup.getPeerName());
            System.out.println("Peer Group name: "
                    + TheNetPeerGroup.getPeerGroupName());
            System.out.println("Peer Group ID  : "
                    + TheNetPeerGroup.getPeerID().toString());
            
        } catch (PeerGroupException ex) {
            // Cannot initialize peer group
            ex.printStackTrace();
            System.exit(-1);
        } catch (IOException ex) {
            ex.printStackTrace();
            System.exit(-1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String GetPrincipal() {
        return (String) JOptionPane.showInputDialog(
                null, "Enter principal", "Principal", JOptionPane.QUESTION_MESSAGE,
                null, null, "");
    }

    private String GetPassword() {
        return (String) JOptionPane.showInputDialog(
                null, "Enter password", "Password", JOptionPane.QUESTION_MESSAGE,
                null, null, "");
    }

    public void SeekRendezVousConnection() 
    {
        System.out.println("Waiting for a rendezvous connection for 25 seconds � + �(maximum)");
        boolean connected = TheNetworkManager.waitForRendezvousConnection(25000);
        System.out.println("Connected: " +  connected);
        //System.out.println("Stopping JXTA");
        //TheNetworkManager.stopNetwork();
        
        if (connected)
        {
	        DiscoveryService ds = TheNetworkManager.getNetPeerGroup().getDiscoveryService();
	        
	        System.out.println("::::::::::::LOCALES:::::::::::::::::::::::::::");
        	try {
	        	Enumeration e = ds.getLocalAdvertisements(DiscoveryService.PEER, "PID", null);
	        	
	        	Advertisement adv;
	    	    while (e.hasMoreElements()) 
	    	    {
	    	        adv = (Advertisement) e.nextElement();
	    	        System.out.println(adv);
	    	    }
        	} catch (IOException ioe){ioe.printStackTrace();}
        	
        	System.out.println("::::::::::::SE ACABARON LOS LOCALES:::::::::::::::::::::::::::");
        	
    	    try {
	        	Thread.currentThread().sleep(10000);
        	} catch (InterruptedException ie){}
        	
        	//startDiscovery(ds);
        }
    }
    
    /**
     * loop forever attempting to discover advertisements every minute
     */
    public void startDiscovery(DiscoveryService ds) {
        long waittime = 60 * 1000L;

        try {
            // Add ourselves as a DiscoveryListener for DiscoveryResponse events
            ds.addDiscoveryListener(this);
            ds.getRemoteAdvertisements(// no specific peer (propagate)
                    null, // Adv type
                    DiscoveryService.ADV, // Attribute = any
                    null, // Value = any
                    null, // one advertisement response is all we are looking for
                    1, // no query specific listener. we are using a global listener
                    null);
            while (true) {
                // wait a bit before sending a discovery message
                try {
                    System.out.println("Sleeping for :" + waittime);
                    Thread.sleep(waittime);
                } catch (Exception e) {
                    // ignored
                }
                System.out.println("Sending a Discovery Message");
                // look for any peer
                ds.getRemoteAdvertisements(
                        // no specific peer (propagate)
                        null,
                        // Adv type
                        DiscoveryService.ADV,
                        // Attribute = name
                        "Name",
                        // Value = the tutorial
                        "Discovery tutorial",
                        // one advertisement response is all we are looking for
                        1,
                        // no query specific listener. we are using a global listener
                        null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public void discoveryEvent(DiscoveryEvent ev) {

        DiscoveryResponseMsg res = ev.getResponse();

        // let's get the responding peer's advertisement
        System.out.println(" [  Got a Discovery Response [" + res.getResponseCount() + " elements]  from peer : " + ev.getSource() + "  ]");

        Advertisement adv;
        Enumeration en = res.getAdvertisements();

        if (en != null) {
            while (en.hasMoreElements()) {
                adv = (Advertisement) en.nextElement();
                System.out.println(adv);
            }
        }
    }

}